<template>
  <canvas id="canvas" width="250" height="250" />
</template>
<script>
export default {
  name: "Seal",
  props: {
    roundText: {
      type: String,
      default: "此处为企业名称"
    },
    rowText: {
      type: String,
      default: "此处文横向文"
    },
    bottomText: {
      type: String,
      default: "此处为下弦文"
    },
    type: {
      type: String,
      default: "circle" // circle || oval
    },
    color: {
      type: String,
      default: "black"
    },
    value: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      sealString: ""
    };
  },
  watch: {
    roundText() {
      this.updateSeal();
    },
    rowText() {
      this.updateSeal();
    },
    bottomText() {
      this.updateSeal();
    },
    type() {
      this.updateSeal();
    },
    color() {
      this.updateSeal();
    }
  },
  mounted() {
    this.updateSeal();
  },
  methods: {
    updateSeal() {
      if (document.getElementById("canvas")) {
        this.type === "circle"
          ? this.updateCircleSeal(this.roundText, this.rowText, this.bottomText, this.color)
          : this.updateOvalSeal(this.roundText, this.rowText, this.bottomText, this.color);
      }
    },
    emitChange(canvas) {
      this.sealString = canvas.toDataURL("image/png");
      this.$emit("input", this.sealString);
      this.$emit("change", this.sealString);
    },
    updateCircleSeal(company, name, downText, color) {
      const canvas = document.getElementById("canvas");
      const context = canvas.getContext("2d");
      context.setTransform(1, 0, 0, 1, 0, 0);
      context.clearRect(0, 0, canvas.width, canvas.height);

      // 绘制印章边框
      const width = canvas.width / 2;
      const height = canvas.height / 2;
      context.lineWidth = 4;
      context.strokeStyle = color;
      context.beginPath();
      context.arc(width, height, 110, 0, Math.PI * 2);
      context.stroke();

      // 画五角星
      this.createStar(context, width, height - 15, 25, color, 0);

      // 绘制印章名称
      context.font = "18px Helvetica";
      context.textBaseline = "middle"; // 设置文本的垂直对齐方式
      context.textAlign = "center"; // 设置文本的水平对对齐方式
      context.lineWidth = 1;
      context.fillStyle = color;
      context.fillText(name, width, height + 30);

      context.translate(width, height); // 平移到此位置

      // 绘制印章单位
      const count = company.length; // 字数
      const isLongName = count > 12;
      context.font = isLongName ? "23px Helvetica" : "28px Helvetica";
      const rangeAngle = isLongName ? Math.PI * 1.3 : count >= 8 ? Math.PI : (Math.PI * 5) / 6;
      const spaceAngle = (Math.PI - rangeAngle) / 2;
      const angle = rangeAngle / (count - 1); // 字间角度
      const chars = company.split("");
      let c;
      for (let i = 0; i < count; i++) {
        c = chars[i]; // 需要绘制的字符
        if (i === 0) context.rotate(-Math.PI + spaceAngle);
        else context.rotate(angle);
        context.save();
        context.translate(90, 0); // 平移到此位置,此时字和x轴垂直
        context.rotate(Math.PI / 2); // 旋转90度,让字平行于x轴
        context.fillText(c, 0, isLongName ? -2 : 3); // 此点为字的中心点
        context.restore();
      }

      context.rotate(spaceAngle);

      // 绘制下弦文
      context.font = isLongName ? "16px Helvetica" : "20px Helvetica";
      const count2 = downText.length; // 字数
      const rangeAngle2 = isLongName ? Math.PI * 0.5 : count2 >= 6 ? (2 / 3) * Math.PI : Math.PI / 2;
      const spaceAngle2 = (Math.PI - rangeAngle2) / 2;
      const angle2 = rangeAngle2 / (count2 - 1); // 字间角度
      const chars2 = downText.split("");
      let c2 = "";
      for (let i = count2 - 1; i >= 0; i--) {
        c2 = chars2[i]; // 需要绘制的字符
        if (i === count2 - 1) context.rotate(spaceAngle2);
        else context.rotate(angle2);
        context.save();
        context.translate(90, 0); // 平移到此位置,此时字和x轴垂直
        context.rotate((Math.PI / 2) * 3); // 旋转90度,让字平行于x轴
        context.fillText(c2, 0, isLongName ? 8 : -2); // 此点为字的中心点
        context.restore();
      }

      this.emitChange(canvas);
    },
    updateOvalSeal(company, name, downText, color) {
      const canvas = document.getElementById("canvas");
      const context = canvas.getContext("2d");
      context.setTransform(1, 0, 0, 1, 0, 0);
      context.clearRect(0, 0, canvas.width, canvas.height);
      const width = canvas.width;
      const height = canvas.height;
      const lineWidth = 2;
      context.strokeStyle = color; // 设置文本颜色
      context.textBaseline = "middle"; // 设置文本的垂直对齐方式
      context.textAlign = "center"; // 设置文本的水平对对齐方式
      context.lineWidth = lineWidth; // 椭圆1宽度
      // 3个参数： 左边距 上边据 宽度 椭圆扁度
      this.BezierEllipse4(context, width / 2, height / 2, (width - lineWidth) / 2, (width - lineWidth) / 3); // 椭圆1

      // 绘制印章类型
      context.font = "16px SimSun";
      context.lineWidth = 1;
      context.fillStyle = color;
      context.fillText(name, width / 2, height / 2);
      context.save();

      // 绘制中文
      const ccircle = {
        x: width / 2,
        y: height / 2,
        radius: width / 3
      };
      let cstartAngle = 160; // 控制字符起始位置度数
      const cendAngle = 20; // 首位字符相隔度数
      const cradius = ccircle.radius - 11; // 圆的半径
      const cangleDecrement = (cstartAngle - cendAngle) / (company.length - 1); // 每个字母占的弧度
      context.font = "18px SimSun";
      const cratioX = 1.5; // 横轴缩放比率
      const cratioY = 1.1; // 纵轴缩放比率
      // 进行缩放（均匀压缩）
      context.scale(cratioX, cratioY);
      for (let cindex = 0; cindex < company.length; cindex++) {
        context.save();
        context.beginPath();
        // 绘制点
        context.translate(
          ccircle.x + Math.cos((Math.PI / 180) * cstartAngle) * cradius - 42,
          ccircle.y - Math.sin((Math.PI / 180) * cstartAngle) * cradius
        );
        context.rotate(Math.PI / 2 - (Math.PI / 180) * cstartAngle); // Math.PI/2为旋转90度  Math.PI/180*X为旋转多少度
        context.fillText(company.charAt(cindex), 0, 0);
        context.strokeText(company.charAt(cindex), 0, 0);
        cstartAngle -= cangleDecrement;
        context.restore();
      }

      context.scale(1, 1);

      // 绘制中文2
      const ccircl2 = {
        x: width / 2,
        y: height / 2,
        radius: width / 3
      };
      let cstartAngl2 = -30; // 控制字符起始位置度数
      const cradiu2 = ccircl2.radius - 25; // 圆的半径
      const cangleDecrement2 = 120 / (downText.length - 1); // 每个字母占的弧度
      context.font = "12px SimSun";
      const cratioX2 = 1.2; // 横轴缩放比率
      const cratioY2 = 1; // 纵轴缩放比率
      // 进行缩放（均匀压缩）
      context.scale(cratioX2, cratioY2);
      for (let cindex = downText.length - 1; cindex >= 0; cindex--) {
        context.save();
        context.beginPath();
        // 绘制点
        context.translate(
          ccircl2.x + Math.cos((Math.PI / 180) * cstartAngl2) * cradiu2 - 55,
          ccircl2.y - Math.sin((Math.PI / 180) * cstartAngl2) * cradiu2 - 5
        );
        context.rotate((Math.PI / 2) * 3 - (Math.PI / 180) * cstartAngl2); // Math.PI/2为旋转90度  Math.PI/180*X为旋转多少度
        context.fillText(downText.charAt(cindex), 0, 0);
        context.strokeText(downText.charAt(cindex), 0, 0);
        cstartAngl2 -= cangleDecrement2;
        context.restore();
      }

      this.emitChange(canvas);
    },
    createStar(context, sx, sy, radius, color, rotato) {
      context.save();
      context.fillStyle = color;
      context.translate(sx, sy); // 移动坐标原点
      context.rotate(Math.PI + rotato); // 旋转
      context.beginPath(); // 创建路径
      let x = Math.sin(0);
      let y = Math.cos(0);
      const dig = (Math.PI / 5) * 4;
      for (let i = 0; i < 5; i++) {
        // 画五角星的五条边
        x = Math.sin(i * dig);
        y = Math.cos(i * dig);
        context.lineTo(x * radius, y * radius);
      }
      context.closePath();
      context.stroke();
      context.fill();
      context.restore();
    },
    BezierEllipse4(ctx, x, y, a, b) {
      const k = 0.5522848;
      const ox = a * k; // 水平控制点偏移量
      const oy = b * k; // 垂直控制点偏移量
      ctx.beginPath();
      // 从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线
      ctx.moveTo(x - a, y);
      ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
      ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
      ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
      ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
      ctx.closePath();
      ctx.stroke();
    }
  }
};
</script>
